Completed
Push — master ( 900d15...0f80c8 )
by Sander
12s
created

angular.controller(ꞌShareCtrlꞌ)   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 6
rs 9.4285
1
/**
2
 * Nextcloud - passman
3
 *
4
 * @copyright Copyright (c) 2016, Sander Brand ([email protected])
5
 * @copyright Copyright (c) 2016, Marcos Zuriaga Miguel ([email protected])
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
23
(function () {
24
	'use strict';
25
26
	/**
27
	 * @ngdoc function
28
	 * @name passmanApp.controller:MainCtrl
29
	 * @description
30
	 * # MainCtrl
31
	 * Controller of the passmanApp
32
	 * This file is part of passman, licensed under AGPLv3
33
	 */
34
	angular.module('passmanApp')
35
		.controller('ShareCtrl', ['$scope', 'VaultService', 'CredentialService', 'SettingsService', '$location', '$routeParams', 'ShareService', 'NotificationService', 'SharingACL', 'EncryptService',
36
			function ($scope, VaultService, CredentialService, SettingsService, $location, $routeParams, ShareService, NotificationService, SharingACL, EncryptService) {
37
				$scope.active_vault = VaultService.getActiveVault();
38
39
				$scope.tabs = [{
40
					title: 'Share with users and groups',
41
					url: 'views/partials/forms/share_credential/basics.html'
42
				}, {
43
					title: 'Share link',
44
					url: 'views/partials/forms/share_credential/link_sharing.html',
45
					color: 'green'
46
				}];
47
				$scope.currentTab = {
48
					title: 'General',
49
					url: 'views/partials/forms/share_credential/basics.html'
50
				};
51
52
				$scope.onClickTab = function (tab) {
53
					$scope.currentTab = tab;
54
				};
55
56
				$scope.isActiveTab = function (tab) {
57
					return tab.url === $scope.currentTab.url;
58
				};
59
60
				if (!SettingsService.getSetting('defaultVault') || !SettingsService.getSetting('defaultVaultPass')) {
61
					if (!$scope.active_vault) {
62
						$location.path('/');
63
					}
64
				} else {
65
					if (SettingsService.getSetting('defaultVault') && SettingsService.getSetting('defaultVaultPass')) {
66
						var _vault = angular.copy(SettingsService.getSetting('defaultVault'));
67
						_vault.vaultKey = angular.copy(SettingsService.getSetting('defaultVaultPass'));
68
						VaultService.setActiveVault(_vault);
69
						$scope.active_vault = _vault;
70
71
					}
72
				}
73
				var storedCredential = SettingsService.getSetting('share_credential');
74
75
				if (!storedCredential) {
76
					$location.path('/vault/' + $routeParams.vault_id);
77
				} else {
78
					$scope.storedCredential = CredentialService.decryptCredential(angular.copy(storedCredential));
79
				}
80
81
				if ($scope.active_vault) {
82
					$scope.$parent.selectedVault = true;
83
				}
84
				$scope.cancel = function () {
85
					SettingsService.setSetting('share_credential', null);
86
					$location.path('/vault/' + $routeParams.vault_id);
87
				};
88
89
90
				$scope.default_permissions = new SharingACL(0);
91
				$scope.default_permissions.addPermission(
92
					$scope.default_permissions.permissions.READ |
93
					$scope.default_permissions.permissions.WRITE |
94
					$scope.default_permissions.permissions.FILES
95
				);
96
97
				var link_acl = angular.copy($scope.default_permissions);
98
				link_acl.removePermission($scope.default_permissions.permissions.WRITE);
99
100
				$scope.share_settings = {
101
					linkSharing: {
102
						enabled: false,
103
						settings: {
104
							expire_time: new Date("2999-12-31T22:59:59"),
105
							expire_views: 5,
106
							acl: link_acl
107
						}
108
					},
109
					credentialSharedWithUserAndGroup: [],
110
					cypher_progress: {
111
						done: 0,
112
						total: 0
113
					},
114
					upload_progress: {
115
						done: 0,
116
						total: 0
117
					}
118
				};
119
120
				var getAcl = function () {
121
					ShareService.getSharedCredentialACL($scope.storedCredential).then(function (aclList) {
122
						var _list = [];
123
						var enc_key = ($scope.storedCredential.shared_key) ? EncryptService.decryptString(angular.copy($scope.storedCredential.shared_key)) : false;
124
						for (var i = 0; i < aclList.length; i++) {
125
							var acl = aclList[i];
126
							if (acl.user_id === null) {
127
								$scope.share_settings.linkSharing = {
128
									enabled: true,
129
									settings: {
130
										expire_time: new Date(acl.expire * 1000),
131
										expire_views: acl.expire_views,
132
										acl: new SharingACL(acl.permissions)
133
									}
134
								};
135
								if (enc_key) {
136
									var hash = window.btoa($scope.storedCredential.guid + '<::>' + enc_key);
137
									$scope.share_link = getShareLink(hash);
138
								}
139
							} else {
140
								var obj = {
141
									userId: acl.user_id,
142
									displayName: acl.user_id,
143
									type: 'user',
144
									acl: new SharingACL(acl.permissions),
145
									acl_id: acl.acl_id,
146
									pending: acl.pending,
147
									credential_guid: acl.item_guid,
148
									created: acl.created
149
								};
150
151
								_list.push(obj);
152
							}
153
154
						}
155
						$scope.share_settings.credentialSharedWithUserAndGroup = _list;
156
					});
157
				};
158
				getAcl();
159
				var acl = new SharingACL(0);
160
161
162
				$scope.$watch('share_settings.upload_progress.done', function () {
163
										if ($scope.share_settings.upload_progress.done === $scope.share_settings.upload_progress.total && $scope.share_settings.upload_progress.total > 0) {
164
						getAcl();
165
					}
166
				});
167
168
				$scope.inputSharedWith = [];
169
170
				$scope.searchUsers = function ($query) {
171
					return ShareService.search($query);
172
				};
173
174
				$scope.hasPermission = function (acl, permission) {
175
					return acl.hasPermission(permission);
176
				};
177
178
				$scope.setPermission = function (acl, permission) {
179
					acl.togglePermission(permission);
180
				};
181
				$scope.shareWith = function (shareWith) {
182
					$scope.inputSharedWith = [];
183
					if (shareWith.length > 0) {
184
						for (var i = 0; i < shareWith.length; i++) {
185
							var obj = {
186
								userId: shareWith[i].uid,
187
								displayName: shareWith[i].text,
188
								type: shareWith[i].type,
189
								acl: angular.copy($scope.default_permissions),
190
								pending: true,
191
								credential_guid: $scope.storedCredential.guid
192
							};
193
							var found = false;
194
							for (var z = 0; z < $scope.share_settings.credentialSharedWithUserAndGroup.length; z++) {
195
								if ($scope.share_settings.credentialSharedWithUserAndGroup[z].userId === shareWith[z].uid) {
196
									found = true;
197
								}
198
							}
199
							if (found === false) {
200
								$scope.share_settings.credentialSharedWithUserAndGroup.push(obj);
201
							}
202
						}
203
					}
204
				};
205
206
				$scope.unshareUser = function (user) {
207
					ShareService.unshareCredentialFromUser($scope.storedCredential, user.userId).then(function (result) {
208
						if (result.result === true) {
209
							var idx = $scope.share_settings.credentialSharedWithUserAndGroup.indexOf(user);
210
							$scope.share_settings.credentialSharedWithUserAndGroup.splice(idx, 1);
211
						}
212
					});
213
				};
214
215
				$scope.unshareCredential = function (credential) {
216
					ShareService.unshareCredential(credential);
217
					var _credential = angular.copy(credential);
218
					var old_key = EncryptService.decryptString(angular.copy(_credential.shared_key));
219
					var new_key = VaultService.getActiveVault().vaultKey;
220
					_credential.shared_key = null;
221
					_credential.unshare_action = true;
222
					_credential.skip_revision = true;
223
224
					_credential = CredentialService.encryptCredential(_credential, old_key);
225
					CredentialService.updateCredential(_credential, true).then(function () {
226
						NotificationService.showNotification('Credential unshared', 4000);
227
						CredentialService.reencryptCredential(_credential.guid, old_key, new_key).then(function () {
228
							getAcl();
229
						});
230
					});
231
				};
232
233
				/**
234
				 * Apply a share to a new user
235
				 * @param user A user object to who we should share the data
236
				 * @param enc_key The shared key we are going to ecnrypt with his public rsa key
237
				 */
238
				$scope.applyShareToUser = function (user, enc_key) {
239
					ShareService.getVaultsByUser(user.userId).then(function (data) {
240
						$scope.share_settings.cypher_progress.total += data.length;
241
242
						user.vaults = data;
243
						var start = new Date().getTime() / 1000;
244
						ShareService.cypherRSAStringWithPublicKeyBulkAsync(user.vaults, enc_key)
245
							.progress(function () {
246
								$scope.share_settings.cypher_progress.done++;
247
								$scope.share_settings.cypher_progress.percent = $scope.share_settings.cypher_progress.done / $scope.share_settings.cypher_progress.total * 100;
248
								$scope.$digest();
249
							})
250
							.then(function (result) {
251
																$scope.share_settings.cypher_progress.times.push({
252
									time: ((new Date().getTime() / 1000) - start),
253
									user: data[0].user_id
254
								});
255
								user.vaults = result;
256
								if (!user.hasOwnProperty('acl_id')) {
257
									$scope.uploadChanges(user);
258
								}
259
								$scope.$digest();
260
							});
261
					});
262
				};
263
264
265
266
				$scope.$on("$locationChangeStart", function(event) {
267
					if(!$scope.sharing_complete){
268
						if(!confirm("Are you sure you want to leave?\nThis will corrupt this credential")){
269
							event.preventDefault();
270
						}
271
					}
272
				});
273
274
				var getShareLink = function(hash){
275
					var port;
276
					var defaultPort = ($location.$$protocol === 'http') ? 80 : 443;
277
					port = (defaultPort !== $location.$$port) ? ':'+ $location.$$port : '';
278
					return $location.$$protocol + '://' + $location.$$host + port + OC.generateUrl('apps/passman/share/public#') + hash;
279
				};
280
281
				$scope.sharing_complete = true;
282
				$scope.applyShare = function () {
283
					$scope.sharing_complete = false;
284
					$scope.share_settings.cypher_progress.percent = 0;
285
					$scope.share_settings.cypher_progress.done = 0;
286
					$scope.share_settings.cypher_progress.total = 0;
287
					$scope.share_settings.cypher_progress.times = [];
288
					$scope.share_settings.cypher_progress.times_total = [];
289
					$scope.share_settings.upload_progress.done = 0;
290
					$scope.share_settings.upload_progress.total = 0;
291
					//Credential is already shared
292
					if ($scope.storedCredential.shared_key && $scope.storedCredential.shared_key !== '' && $scope.storedCredential.shared_key !== null) {
293
												var enc_key = EncryptService.decryptString(angular.copy($scope.storedCredential.shared_key));
294
						if ($scope.share_settings.linkSharing.enabled) {
295
							var expire_time = new Date(angular.copy($scope.share_settings.linkSharing.settings.expire_time)).getTime() / 1000;
296
							var shareObj = {
297
								item_id: $scope.storedCredential.credential_id,
298
								item_guid: $scope.storedCredential.guid,
299
								permissions: $scope.share_settings.linkSharing.settings.acl.getAccessLevel(),
300
								expire_timestamp: expire_time,
301
								expire_views: $scope.share_settings.linkSharing.settings.expire_views
302
							};
303
							ShareService.createPublicSharedCredential(shareObj).then(function () {
304
								var hash = window.btoa($scope.storedCredential.guid + '<::>' + enc_key);
305
								$scope.share_link = getShareLink(hash);
306
							});
307
						}
308
309
						var list = $scope.share_settings.credentialSharedWithUserAndGroup;
310
311
						for (var i = 0; i < list.length; i++) {
312
							var iterator = i;
313
							var target_user = list[i];
314
							if (target_user.hasOwnProperty('created')) {
315
								var acl = {
316
									user_id: target_user.userId,
317
									permission: target_user.acl.getAccessLevel()
318
								};
319
								ShareService.updateCredentialAcl($scope.storedCredential, acl);
320
							} else {
321
								$scope.applyShareToUser(list[iterator], enc_key);
322
							}
323
						}
324
						NotificationService.showNotification('Saved!', 4000);
325
						$scope.sharing_complete = true;
326
					} else {
327
328
						ShareService.generateSharedKey(20).then(function (key) {
329
330
							var encryptedSharedCredential = angular.copy($scope.storedCredential);
331
							var old_key = VaultService.getActiveVault().vaultKey;
332
333
							CredentialService.reencryptCredential(encryptedSharedCredential.guid, old_key, key).progress(function () {
334
															}).then(function (data) {
335
								var _credential = data.cryptogram;
336
								_credential.set_share_key = true;
337
								_credential.skip_revision = true;
338
								_credential.shared_key = EncryptService.encryptString(key);
339
								CredentialService.updateCredential(_credential, true).then(function () {
340
									NotificationService.showNotification('Credential shared', 4000);
341
									$scope.sharing_complete = true;
342
								});
343
							});
344
345
							var list = $scope.share_settings.credentialSharedWithUserAndGroup;
346
							for (var i = 0; i < list.length; i++) {
347
								if (list[i].type === "user") {
348
									$scope.applyShareToUser(list[i], key);
349
								}
350
							}
351
352
							if ($scope.share_settings.linkSharing.enabled) {
353
								var expire_time = new Date(angular.copy($scope.share_settings.linkSharing.settings.expire_time)).getTime() / 1000;
354
								var shareObj = {
355
									item_id: $scope.storedCredential.credential_id,
356
									item_guid: $scope.storedCredential.guid,
357
									permissions: $scope.share_settings.linkSharing.settings.acl.getAccessLevel(),
358
									expire_timestamp: expire_time,
359
									expire_views: $scope.share_settings.linkSharing.settings.expire_views
360
								};
361
								ShareService.createPublicSharedCredential(shareObj).then(function () {
362
									var hash = window.btoa($scope.storedCredential.guid + '<::>' + key);
363
									$scope.share_link = getShareLink(hash);
364
								});
365
							}
366
367
						});
368
					}
369
				};
370
371
				$scope.uploadChanges = function (user) {
372
					$scope.share_settings.upload_progress.total++;
373
374
					user.accessLevel = angular.copy(user.acl.getAccessLevel());
375
					ShareService.shareWithUser(storedCredential, user)
376
						.then(function () {
377
							$scope.share_settings.upload_progress.done++;
378
							$scope.share_settings.upload_progress.percent = $scope.share_settings.upload_progress.done / $scope.share_settings.upload_progress.total * 100;
379
						});
380
				};
381
382
				$scope.calculate_total_time = function () {
383
					$scope.share_settings.cypher_progress.times = $scope.share_settings.cypher_progress.times || [];
384
					var total = 0;
385
					for (var i = 0; i < $scope.share_settings.cypher_progress.times.length; i++) {
386
						total += $scope.share_settings.cypher_progress.times[i].time;
387
					}
388
					return total;
389
				};
390
			}]);
391
}());
392